/*************************************************************************
 *  Copyright © 2023-2030 Administrator. All rights reserved.
 *------------------------------------------------------------------------
 *  公司：DefaultCompany
 *  项目：CustomBuildProcess
 *  文件：CustomBuildSettingsWindow.cs
 *  作者：Administrator
 *  日期：2024/9/28 22:10:41
 *  功能：Nothing
 *  Bug:
 *  1、当修改软件名称时，这个时候打包会以修改前的名称进行打包，原因是打包时没有重新生成buildPlayerOptions。
*************************************************************************/

using System;
using System.IO;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Resources;
using UnityEditor.IMGUI.Controls;

namespace CustomBuildProcess.Editor
{
    public class CustomBuildSettingsWindow : EditorWindow
    {
        public static CustomBuildSettingsWindow instance;

        public BuildInfoConfig configAsset;
        public BuildInfo lastBuildInfo;
        public BuildConfigItem logConfigItem;
        public CustomBuildProcessConfig buildProcessConfig;

        public string appID;
        public string platform;
        public string feature;
        public string model;
        public string language;
        public string type;
        private int selectedPlatformIndex;
        private int selectedFeatureIndex;
        private int selectedModelIndex;
        private int selectedLanguageIndex;
        private int selectedTypeIndex;

        public string companyName;
        public string productName;
        public string version;
        private int selectedVersionIndex;  // 当前选中的版本索引
        public Texture2D defaultIcon;
        public string buildLog;
        public string buildTime;

        private Vector2 scrollArea;
        private bool appIDWarning;
        private bool companyNameWarning;
        private bool productNameWarning;
        private bool versionWarning;
        //private bool iconWarning;
        private bool logWarning;
        private string appIDWarningInfo;
        private string companyNameWarningInfo;
        private string productNameWarningInfo;
        private string versionWarningInfo;
        //private string iconWarningInfo;
        private string logWarningInfo;

        private Texture2D[] availableIcons; // 可用图标列表
        private Vector2 iconsScrollPos;
        private int selectedIconIndex = -1; // 当前选中的图标索引
        private Texture2D iconToAdd;           // 待添加的图标
        private Texture2D iconLabelBg;
        public Texture2D predefaultIcon;
        private bool isAddingIcon = false;

        private bool isAddVersion;
        private bool isRemoveButtonEnabled; // 控制按钮是否启用
        private bool isAutoRun = false;

        private static Vector2 originSize = new Vector2(600, 620);
        private static Vector2 extendSize = new Vector2(600, 660);

        private GUIContent helpIcon;
        private GUIContent editorIcon;
        private GUIContent plusIcon;
        private GUIContent minusIcon;
        private GUIContent settingsIcon;

        private SearchField searchField;
        public string searchText = "";

        // 显示自定义窗口的方法
        public static void ShowWindow()
        {
            instance = GetWindow<CustomBuildSettingsWindow>("Custom Build Process");
            instance.minSize = instance.maxSize = originSize;
            instance.wantsMouseMove = true;
            instance.Show();
            instance.UpdateBuildPlayerOptionsToMemory(BuildProcess.buildPlayerOptions);
        }

        private void ResizeWindow(Vector2 size)
        {
            Rect newPos = position;
            newPos.width = size.x;
            newPos.height = size.y;
            position = newPos;

            // 可选：设置最小最大尺寸限制
            minSize = new Vector2(size.x, size.y);
            maxSize = new Vector2(size.x, size.y);
        }

        private void OnEnable()
        {
            BuildProcess.OnPostprocessBuildCall -= OnPreprocessBuild;
            BuildProcess.OnPostprocessBuildCall += OnPreprocessBuild;
            BuildProcess.OnPostprocessBuildCall -= OnPostprocessBuild;
            BuildProcess.OnPostprocessBuildCall += OnPostprocessBuild;

            InitWindow();
        }

        private void OnDestroy()
        {
            BuildProcess.OnPostprocessBuildCall -= OnPreprocessBuild;
            BuildProcess.OnPostprocessBuildCall -= OnPostprocessBuild;

            RemoveBuildSettingsFromMemory();
            RemoveBuildPlayerOptionsToMemory();
        }

        #region 初始化
        /// <summary>
        /// 初始化
        /// </summary>
        private void InitWindow()
        {
            isAddVersion = false;
            configAsset = AssetDatabase.LoadAssetAtPath<BuildInfoConfig>(PathManager.BuildConfigPath);

            logConfigItem = Resources.Load<BuildConfigItem>(PathManager.BuildConfigItemPath);
            buildProcessConfig = Resources.Load<CustomBuildProcessConfig>(PathManager.CustomBuildProcessConfigPath);

            helpIcon = EditorGUIUtility.IconContent("_Help");
            editorIcon = EditorGUIUtility.IconContent("editicon.sml");
            plusIcon = EditorGUIUtility.IconContent("Toolbar Plus");
            minusIcon = EditorGUIUtility.IconContent("Toolbar Minus");
            settingsIcon = EditorGUIUtility.IconContent("SettingsIcon");

            iconLabelBg = GetTexture(1, 1, new Color(0.2f, 0.2f, 0.2f, 0.5f));
            LoadIcons();

            searchField = new SearchField();

            //这里在打错包的时候，当我们没有关闭窗口的时候，去重新编译脚本，会调用该函数
            //因为重新编译不会序列化我们输入的内容，所以面板上的内容会重新加载BuildSetting中的数据
            //但是这里我们要求重新编译后面板上的内容不变，使用EditorPre进行数据的存储
            //在关闭窗口的时候，把这些存储的数据进行删除
            //首先从EditorPre在家数据，如果没有那么从BuildSetting中或BuildSettingConfig加载数据
            if (IsHaveBuildSettingsMemoryInfo())
                UpdateLastBuildSettingsFromMemory();
            else
                UpdateLastBuildInfo();
        }

        #endregion

        #region 绘制界面

        private void OnGUI()
        {
            DrawHeader();

            GUILayout.Space(10f);

            DrawTitle();

            GUILayout.Space(10f);

            DrawVersionSelect();

            GUILayout.Space(10f);

            DrawAppID();

            DrawPlaform();

            DrawModel();

            DrawFeature();

            DrawLanguage();

            DrawType();

            DrawCompanyName();

            DrawProductName();

            DrawVersion();

            GUILayout.Space(10f);

            DrawIcon();

            GUILayout.Space(10f);

            DrawBuildLog();

            GUILayout.FlexibleSpace();

            DrawBuildButton();

            GUILayout.Space(5);
        }

        /// <summary>
        /// 绘制头部
        /// </summary>
        private void DrawHeader()
        {
            EditorGUILayout.BeginHorizontal(GUILayout.Height(20));
            GUILayout.FlexibleSpace();

            if (GUILayout.Button(settingsIcon, GUILayout.Height(18)))
            {
                SettingsService.OpenProjectSettings("Project/Custom Build Process");
            }

            searchText = searchField.OnToolbarGUI(searchText, GUILayout.Height(18));

            EditorGUILayout.Space();

            EditorGUILayout.EndHorizontal();

            DrawLineHorizantal_Bottom(new Color(0.137f, 0.137f, 0.137f, 1F));
        }

        public static void DrawLineHorizantal_Bottom(Color color, float p1XOffset = 0, float p2XOffset = 0, float yOffset = 0)
        {
            Rect lineRect = GUILayoutUtility.GetLastRect();
            Handles.color = color;
            Handles.DrawLine(new Vector2(lineRect.x + p1XOffset, lineRect.y + lineRect.height + yOffset), new Vector2(lineRect.x + lineRect.width + p2XOffset, lineRect.y + lineRect.height + yOffset));
        }

        /// <summary>
        /// 绘制标题
        /// </summary>
        private void DrawTitle()
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label("Build Settings", new GUIStyle { fontSize = 20, padding = new RectOffset() { left = 5 }, fontStyle = FontStyle.Bold, normal = { textColor = Color.white } }); ;
            if (GUILayout.Button(helpIcon, "IconButton"))
            {
                Application.OpenURL(PathManager.BuildLogDocumentPath);
            }

            GUILayout.FlexibleSpace();
            GUILayout.Label(buildTime);
            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制版本选择
        /// </summary>
        private void DrawVersionSelect()
        {
            GUILayout.BeginHorizontal();
            {
                GUILayout.Label("All Versions", GUILayout.Width(146));
                string[] versionsDisplayName = configAsset.GetAllVersionsDisplayName();
                EditorGUI.BeginChangeCheck();
                int selectedIndex = EditorGUILayout.Popup(selectedVersionIndex, versionsDisplayName);
                if (selectedIndex != selectedVersionIndex)
                {
                    selectedVersionIndex = selectedIndex;
                    lastBuildInfo = configAsset.GetBuildInfo(selectedVersionIndex);

                    UpdateBuildInfo(selectedVersionIndex, lastBuildInfo);

                    //每次切换版本时，取消添加版本
                    isAddVersion = false;
                }
                if (EditorGUI.EndChangeCheck())
                {
                    EditorPrefs.SetInt("SelectedVersionIndex", selectedVersionIndex);
                }

                isRemoveButtonEnabled = selectedVersionIndex >= 0 && selectedVersionIndex < versionsDisplayName.Length;

                // 保存当前的GUI.enabled状态
                bool previousGuiState = GUI.enabled;

                // 设置新的GUI.enabled状态
                GUI.enabled = isRemoveButtonEnabled;

                if (GUILayout.Button("Add", GUILayout.Width(60)))
                {
                    isAddVersion = true;
                    GUI.FocusControl(null);

                    //这里的版本可以使用最后一个版本+1
                    version = configAsset.GetVersion(versionsDisplayName.Length - 1);

                    Regex regex = new Regex(@"\.(\d+)(?=[^.\r\n]*$)");
                    Match match = regex.Match(version);

                    if (match.Success)
                    {
                        Group group = match.Groups[1];
                        int lastNumber = int.Parse(group.Value);
                        string replacement = $".{lastNumber + 1}";

                        // 替换最后一个数字
                        version = regex.Replace(version, m => replacement);
                    }

                    buildLog = "";

                    selectedVersionIndex = versionsDisplayName.Length;
                }

                //这里需要优化
                //1、当删除的是最后一个后，这里仍然是获取的selectedVersionIndex处的版本，
                //但是这个时候这里仍然是获取的selectedVersionIndex处的版本超出了versions范围，因此获取不到
                //这里应该删除后获取到最后一个版本
                //2、当删除的是中间的版本时，获取到的是selectedVersionIndex处的版本，因为selectedIndex没有变化
                //所以虽然版本号变化了，但是内容没有更新
                if (GUILayout.Button("Remove", GUILayout.Width(60)))
                {
                    bool result = EditorUtility.DisplayDialog("提示", "你确定要执行此操作吗？", "确认", "取消");
                    if (result)
                    {
                        RemoveBuildInfo(selectedVersionIndex);

                        int count = configAsset.GetAllVersionCount();
                        selectedVersionIndex = count - 1;

                        if (count > 0)
                        {
                            lastBuildInfo = configAsset.GetBuildInfo(selectedVersionIndex);

                            UpdateBuildInfo(selectedVersionIndex, lastBuildInfo);
                        }
                    }
                }

                // 恢复之前的GUI.enabled状态
                GUI.enabled = previousGuiState;
            }
            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制应用ID
        /// </summary>
        private void DrawAppID()
        {
            if (appIDWarning)
            {
                EditorGUILayout.HelpBox(appIDWarningInfo, MessageType.Warning);
            }

            GUILayout.BeginHorizontal();
            EditorGUI.BeginChangeCheck();

            appID = EditorGUILayout.TextField(new GUIContent("App ID*",
                "软件开发人员看到软件ID能准确定位到具体的工程，\r\n" +
                "且ID不可重复，考虑使用SVN中的字段来拼接而成\r\n" +
                "一个ID包含：车型+产品类型+平台类型\r\n" +
                "1、例如SVN中这个工程：svn/VR_Diagnosis/QinEV2306\r\n" +
                "2、软件ID应为：QinEVDiagnosisVR，即：秦EV故障诊断VR\r\n" +
                "3、其中，平台类型中的PC可以不用，例如SVN中这个工程：svn/PC_Mechanic/QinPlus23\r\n" +
                "4、软件ID直接用QinPlusMechanic，即：秦PLUSEV虚拟拆装电脑版"

                ), appID);
            if (!string.IsNullOrEmpty(appID))
            {
                if (appIDWarning)
                {
                    ResizeWindow(originSize);
                    appIDWarning = false;
                }
            }
            else
            {
                Rect textFieldRect = GUILayoutUtility.GetLastRect();
                textFieldRect.x += 150;

                EditorGUI.LabelField(
                    textFieldRect,
                    "车型+产品类型+平台类型,例如:QinEVDiagnosisVR，即:秦EV故障诊断VR",
                    new GUIStyle(GUI.skin.label)
                    {
                        normal = { textColor = Color.gray },
                        alignment = TextAnchor.MiddleLeft,
                        padding = new RectOffset(5, 0, 0, 0) // 调整文字位置
                    }
                );
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("AppID", appID);
            }
            Undo.RecordObject(this, "App ID Changed");

            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制软件平台
        /// </summary>
        private void DrawPlaform()
        {
            GUILayout.BeginHorizontal();
            EditorGUI.BeginChangeCheck();
            int selectedIndex = EditorGUILayout.Popup(new GUIContent("Platform*", "Platform"), selectedPlatformIndex, logConfigItem.GetPlatformsValues().ToArray());
            if (selectedIndex != selectedPlatformIndex)
            {
                selectedPlatformIndex = selectedIndex;
                platform = logConfigItem.platforms[selectedPlatformIndex].key;
            }

            //用于处理当最后一个元素被删除时，这个时候选择最后一个
            if (selectedPlatformIndex > logConfigItem.platforms.Count - 1)
            {
                selectedPlatformIndex = logConfigItem.platforms.Count - 1;
                platform = logConfigItem.platforms[selectedPlatformIndex].key;
            }


            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("Platform", platform);
            }
            Undo.RecordObject(this, "Platform Changed");
            if (GUILayout.Button(editorIcon, GUILayout.Width(30)))
            {
                LogItemOperateWindow.ShowWindow(this, "platforms");
            }
            GUILayout.EndHorizontal();
        }



        /// <summary>
        /// 绘制软件特点（关于什么类型的软件）
        /// </summary>
        private void DrawFeature()
        {
            GUILayout.BeginHorizontal();
            EditorGUI.BeginChangeCheck();
            int selectedIndex = EditorGUILayout.Popup(new GUIContent("Feature*", "Product Type"), selectedFeatureIndex, logConfigItem.GetFeaturesValues().ToArray());
            if (selectedIndex != selectedFeatureIndex)
            {
                selectedFeatureIndex = selectedIndex;
                feature = logConfigItem.features[selectedFeatureIndex].key;
            }

            if (selectedFeatureIndex > logConfigItem.features.Count - 1)
            {
                selectedFeatureIndex = logConfigItem.features.Count - 1;
                feature = logConfigItem.features[selectedFeatureIndex].key;
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("Feature", feature);
            }
            Undo.RecordObject(this, "Feature Changed");
            if (GUILayout.Button(editorIcon, GUILayout.Width(30)))
            {
                LogItemOperateWindow.ShowWindow(this, "features");
            }
            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制软件用的是那款车型
        /// </summary>
        private void DrawModel()
        {
            GUILayout.BeginHorizontal();
            EditorGUI.BeginChangeCheck();

            int selectedIndex = EditorGUILayout.Popup(new GUIContent("Model", "Vehicle Model"), selectedModelIndex, logConfigItem.GetModelsValues().ToArray());
            if (selectedIndex != selectedModelIndex)
            {
                selectedModelIndex = selectedIndex;
                model = logConfigItem.models[selectedModelIndex].key;
            }

            if (selectedModelIndex > logConfigItem.models.Count - 1)
            {
                selectedModelIndex = logConfigItem.models.Count - 1;
                model = logConfigItem.models[selectedModelIndex].key;
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("Model", model);
            }
            Undo.RecordObject(this, "Model Changed");

            if (GUILayout.Button(editorIcon, GUILayout.Width(30)))
            {
                LogItemOperateWindow.ShowWindow(this, "models");
            }
            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制软件语言
        /// </summary>
        private void DrawLanguage()
        {
            GUILayout.BeginHorizontal();
            EditorGUI.BeginChangeCheck();

            int selectedIndex = EditorGUILayout.Popup(new GUIContent("Language*", "Language"), selectedLanguageIndex, logConfigItem.GetLanguagesValues().ToArray());
            if (selectedIndex != selectedLanguageIndex)
            {
                selectedLanguageIndex = selectedIndex;
                language = logConfigItem.languages[selectedLanguageIndex].key;
            }

            if (selectedLanguageIndex > logConfigItem.languages.Count - 1)
            {
                selectedLanguageIndex = logConfigItem.languages.Count - 1;
                language = logConfigItem.languages[selectedLanguageIndex].key;
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("Language", language);
            }
            Undo.RecordObject(this, "Language Changed");

            if (GUILayout.Button(editorIcon, GUILayout.Width(30)))
            {
                LogItemOperateWindow.ShowWindow(this, "languages");
            }
            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制软件启动方式
        /// </summary>
        private void DrawType()
        {
            GUILayout.BeginHorizontal();
            EditorGUI.BeginChangeCheck();

            int selectedIndex = EditorGUILayout.Popup(new GUIContent("Release Type*", "Release Type"), selectedTypeIndex, logConfigItem.GetTypesValues().ToArray());
            if (selectedIndex != selectedTypeIndex)
            {
                selectedTypeIndex = selectedIndex;
                type = logConfigItem.releaseTypes[selectedTypeIndex].key;
            }

            if (selectedTypeIndex > logConfigItem.releaseTypes.Count - 1)
            {
                selectedTypeIndex = logConfigItem.releaseTypes.Count - 1;
                type = logConfigItem.releaseTypes[selectedTypeIndex].key;
            }

            if (EditorGUI.EndChangeCheck())
            {
                if (versionWarning)
                {
                    versionWarning = false;
                    ResizeWindow(originSize);
                }

                EditorPrefs.SetString("Type", type);
            }
            Undo.RecordObject(this, "Type Changed");

            if (GUILayout.Button(editorIcon, GUILayout.Width(30)))
            {
                LogItemOperateWindow.ShowWindow(this, "types");
            }

            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制公司名称
        /// </summary>
        private void DrawCompanyName()
        {
            if (companyNameWarning)
            {
                EditorGUILayout.HelpBox(companyNameWarningInfo, MessageType.Warning);
            }
            EditorGUI.BeginChangeCheck();
            // 公司名称输入框
            companyName = EditorGUILayout.TextField("Company Name*", companyName);
            if (!string.IsNullOrEmpty(companyName))
            {
                if (companyNameWarning)
                {
                    companyNameWarning = false;
                    ResizeWindow(originSize);
                }
            }
            else
            {
                Rect textFieldRect = GUILayoutUtility.GetLastRect();
                textFieldRect.x += 150;

                EditorGUI.LabelField(
                    textFieldRect,
                    "Enter the company name . . .",
                    new GUIStyle(GUI.skin.label)
                    {
                        normal = { textColor = Color.gray },
                        alignment = TextAnchor.MiddleLeft,
                        padding = new RectOffset(5, 0, 0, 0) // 调整文字位置
                    }
                );
            }
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("CompanyName", companyName);
            }
            Undo.RecordObject(this, "Company Name Changed");
        }

        /// <summary>
        /// 绘制产品名称
        /// </summary>
        private void DrawProductName()
        {
            if (productNameWarning)
            {
                EditorGUILayout.HelpBox(productNameWarningInfo, MessageType.Warning);
            }
            EditorGUI.BeginChangeCheck();
            // 产品名称输入框
            productName = EditorGUILayout.TextField("Software Name*", productName);
            if (!string.IsNullOrEmpty(productName))
            {
                if (productNameWarning)
                {
                    productNameWarning = false;
                    ResizeWindow(originSize);
                }
            }
            else
            {
                Rect textFieldRect = GUILayoutUtility.GetLastRect();
                textFieldRect.x += 150;

                EditorGUI.LabelField(
                    textFieldRect,
                    "Enter the software Name . . .",
                    new GUIStyle(GUI.skin.label)
                    {
                        normal = { textColor = Color.gray },
                        alignment = TextAnchor.MiddleLeft,
                        padding = new RectOffset(5, 0, 0, 0) // 调整文字位置
                    }
                );
            }
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("ProductName", productName);
            }
            Undo.RecordObject(this, "Product Name Changed");
        }

        /// <summary>
        /// 绘制版本
        /// </summary>
        private void DrawVersion()
        {
            if (versionWarning)
            {
                EditorGUILayout.HelpBox(versionWarningInfo, MessageType.Warning);
            }
            EditorGUI.BeginChangeCheck();
            // 版本号输入框
            string version1 = EditorGUILayout.TextField(new GUIContent("Version*",
                "Allow the same version to exist when the type are different\r\n\n" +
                "版本号一般有3位构成，例如Version：1.0.1\r\n" +
                "1、第一位由大版本来定，开发期一直用0，发货时改为1，以后有更新大版本再加\r\n" +
                "2、第一个小数点后的由策划定，默认用0，有多个功能更新会周知增加\r\n" +
                "3、第二个小数点后的数字为打包每次自动加1"
                ), version);
            if (version1 != version)
            {
                version = version1;
                if (versionWarning)
                {
                    versionWarning = false;
                    ResizeWindow(originSize);
                }
            }
            if (string.IsNullOrEmpty(version1))
            {
                Rect textFieldRect = GUILayoutUtility.GetLastRect();
                textFieldRect.x += 150;

                EditorGUI.LabelField(
                    textFieldRect,
                    "Enter the software version . . .",
                    new GUIStyle(GUI.skin.label)
                    {
                        normal = { textColor = Color.gray },
                        alignment = TextAnchor.MiddleLeft,
                        padding = new RectOffset(5, 0, 0, 0) // 调整文字位置
                    }
                );
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString("Version", version);
            }
            Undo.RecordObject(this, "Version Changed");
        }

        /// <summary>
        /// 绘制图标
        /// </summary>
        private void DrawIcon()
        {
            //if (iconWarning)
            //{
            //    EditorGUILayout.HelpBox(iconWarningInfo, MessageType.Warning);
            //}

            GUILayout.BeginHorizontal("Box", GUILayout.Height(150));

            DrawDefaultIcon();

            GUILayout.FlexibleSpace();

            DrawPresetIcons();

            GUILayout.Space(10);

            DrawPresetIconAdd();

            GUILayout.Space(10);

            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制默认图标
        /// </summary>
        private void DrawDefaultIcon()
        {
            GUILayout.BeginVertical(GUILayout.Width(50));
            {
                GUILayout.Label("Default Icon");
                GUILayout.FlexibleSpace();
                // 图标选择  对这里里图标进行优化，可以进行一些内置的ICON可以直接选，也可以从别的地方拿
                defaultIcon = (Texture2D)EditorGUILayout.ObjectField("", defaultIcon, typeof(Texture2D), false, GUILayout.Width(100));
                if (defaultIcon != null)
                {
                    //if (iconWarning)
                    //{
                    //    iconWarning = false;
                    //    ResizeWindow(originSize);
                    //}
                }
                if (defaultIcon != predefaultIcon)
                {
                    EditorPrefs.SetString("DefaultIcon", defaultIcon == null ? "" : AssetDatabase.GetAssetPath(defaultIcon));
                    predefaultIcon = defaultIcon;
                }
                GUILayout.FlexibleSpace();
                Undo.RecordObject(this, "Default Icon Changed");
            }
            GUILayout.EndVertical();
        }

        /// <summary>
        /// 绘制预设图标
        /// </summary>
        private void DrawPresetIcons()
        {
            GUILayout.BeginVertical(GUILayout.Width(285));
            {
                GUILayout.Label("Preset Icons");

                // 绘制图标选择列表（滚动区域）
                iconsScrollPos = GUILayout.BeginScrollView(iconsScrollPos, GUILayout.Height(132));
                int columns = 4; // 一行显示几个图标
                int rowCount = Mathf.CeilToInt(availableIcons.Length / (float)columns);
                for (int row = 0; row < rowCount; row++)
                {
                    GUILayout.BeginHorizontal();
                    for (int col = 0; col < columns; col++)
                    {
                        int index = row * columns + col;
                        if (index < availableIcons.Length)
                        {
                            Texture2D icon = availableIcons[index];

                            GUILayout.BeginVertical();

                            if (GUILayout.Button(icon, GUILayout.Width(64), GUILayout.Height(64)))
                            {
                                // 当用户点击图标时，将图标赋值为 defaultIcon
                                predefaultIcon = defaultIcon;
                                defaultIcon = icon;
                                selectedIconIndex = index;
                            }

                            GUILayout.Space(-17);

                            GUIStyle labelStyle = new GUIStyle("label");
                            labelStyle.normal.background = iconLabelBg;
                            labelStyle.fontSize = 12;
                            GUIContent name = new GUIContent(icon.name, icon.name);

                            GUILayout.Label(name, labelStyle, GUILayout.Width(62));

                            GUILayout.EndHorizontal();
                        }
                    }
                    GUILayout.FlexibleSpace();

                    GUILayout.EndHorizontal();
                }
                GUILayout.EndScrollView();
            }
            GUILayout.EndVertical();
        }

        /// <summary>
        /// 绘制添加图标
        /// </summary>
        private void DrawPresetIconAdd()
        {
            GUILayout.BeginVertical(GUILayout.Width(50));
            {
                GUILayout.Space(10);
                GUILayout.FlexibleSpace();
                if (GUILayout.Button(plusIcon))
                {
                    // 打开 Object Picker 选择图标
                    EditorGUIUtility.ShowObjectPicker<Texture2D>(null, false, "", 0);
                    isAddingIcon = true;
                }

                // 当用户通过 Object Picker 选择图标时获取结果
                if (Event.current.commandName == "ObjectSelectorUpdated")
                {
                    if (isAddingIcon)
                    {
                        iconToAdd = (Texture2D)EditorGUIUtility.GetObjectPickerObject();
                    }
                }

                // 将选中的图标添加到列表
                if (iconToAdd != null && isAddingIcon)
                {
                    AddIcon(iconToAdd);
                    iconToAdd = null;  // 清空选择
                    isAddingIcon = false;
                }

                if (GUILayout.Button(minusIcon))
                {
                    RemoveIcon(selectedIconIndex);
                }
                GUILayout.FlexibleSpace();
            }
            GUILayout.EndVertical();
        }


        /// <summary>
        /// 绘制打包日志
        /// </summary>
        private void DrawBuildLog()
        {
            GUILayout.BeginHorizontal();
            {
                EditorGUILayout.LabelField("Build Log*", EditorStyles.boldLabel, GUILayout.Width(130));

                //GUIStyle gUIStyle = new GUIStyle(EditorStyles.boldLabel);
                //gUIStyle.normal.textColor = new Color(0,1,0);
                //EditorGUILayout.LabelField($"账号：{BuildConfigItem.account}", gUIStyle, GUILayout.Width(80));
                //EditorGUILayout.LabelField($"密码：{BuildConfigItem.password}", gUIStyle, GUILayout.Width(100));

                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Import", GUILayout.Width(50)))
                {

                    if (!string.IsNullOrEmpty(logConfigItem.GetCuttingBoardLog()))
                    {
                        buildLog = logConfigItem.GetCuttingBoardLog();
                        ShowNotification(new GUIContent("Import successful"));
                    }
                    else
                        ShowNotification(new GUIContent("Cutting board has no information"));
                }

                if (GUILayout.Button("Export", GUILayout.Width(50)))
                {
                    logConfigItem.cuttingBoardLog = buildLog;
                    EditorUtility.SetDirty(logConfigItem);
                    AssetDatabase.SaveAssets();
                    ShowNotification(new GUIContent("Export successful"));
                }

                if (GUILayout.Button("Open Log File", GUILayout.Width(100)))
                {
                    OpenBuildLog();
                }
            }
            GUILayout.EndHorizontal();

            if (logWarning)
            {
                EditorGUILayout.HelpBox(logWarningInfo, MessageType.Warning);
            }
            scrollArea = GUILayout.BeginScrollView(scrollArea, GUILayout.Height(100));
            {
                EditorGUI.BeginChangeCheck();

                buildLog = EditorGUILayout.TextArea(buildLog, GUILayout.ExpandHeight(true));
                if (!string.IsNullOrEmpty(buildLog))
                {
                    if (logWarning)
                    {
                        logWarning = false;
                        ResizeWindow(originSize);
                    }
                }
                else
                {
                    Rect textFieldRect = GUILayoutUtility.GetLastRect();

                    EditorGUI.LabelField(
                        textFieldRect,
                        "Enter the build log . . .",
                        new GUIStyle(GUI.skin.label)
                        {
                            normal = { textColor = Color.gray },
                            alignment = TextAnchor.MiddleCenter,
                            fontSize = 30,
                        }
                    );
                }
                if (EditorGUI.EndChangeCheck())
                {
                    EditorPrefs.SetString("BuildLog", buildLog);
                }
            }
            GUILayout.EndScrollView();
            Undo.RecordObject(this, "Build Log Changed");

        }

        #endregion

        #region ICON处理

        private void LoadIcons()
        {
            string[] guids = AssetDatabase.FindAssets("t:Texture2D", new[] { PathManager.PresetIconPath() });

            availableIcons = new Texture2D[guids.Length];

            for (int i = 0; i < guids.Length; i++)
            {
                string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
                Texture2D icon = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
                availableIcons[i] = icon;
            }
        }

        /// <summary>
        /// 添加图标
        /// </summary>
        /// <param name="icon"></param>
        private void AddIcon(Texture2D icon)
        {
            if (icon == null) return;

            string assetPath = AssetDatabase.GetAssetPath(icon);

            if (!File.Exists(assetPath))
            {
                Debug.Log($"Add icon failed: {assetPath}");

                return;
            }

            string iconName = Path.GetFileName(assetPath);
            string destinationPath = PathManager.IconPath(iconName);

            // 检查是否已经存在同名文件
            if (!File.Exists(destinationPath))
            {
                // 将图标复制到 Icons 文件夹
                File.Copy(assetPath, destinationPath);
                AssetDatabase.Refresh();

                // 重新加载图标列表
                LoadIcons();
            }
        }

        /// <summary>
        /// 删除图标方法
        /// </summary>
        /// <param name="index"></param>
        private void RemoveIcon(int index)
        {
            if (index >= 0 && index < availableIcons.Length)
            {
                Texture2D icon = availableIcons[index];
                // 这里对于FXB的图标作为内置图标不允许删除
                if (icon.name.Contains("FXB"))
                {
                    EditorUtility.DisplayDialog("Error", "FXB内置图标不允许删除", "OK");
                    return;
                }

                // 获取图标的路径
                string assetPath = AssetDatabase.GetAssetPath(icon);
                string iconName = Path.GetFileName(assetPath);
                string fullPath = PathManager.IconPath(iconName);

                // 删除文件并刷新资源库
                if (File.Exists(fullPath))
                {
                    File.Delete(fullPath);
                    AssetDatabase.Refresh();

                    // 重新加载图标列表
                    LoadIcons();

                    // 如果删除的是当前选中的图标，重置默认图标
                    if (selectedIconIndex == index)
                    {
                        defaultIcon = null;
                        selectedIconIndex = -1;
                    }
                }
            }
        }

        /// <summary>
        /// 获取贴图
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="color"></param>
        private Texture2D GetTexture(int width, int height, Color color)
        {
            Texture2D backgroundTexture = new Texture2D(width, height);
            backgroundTexture.SetPixel(0, 0, color);
            backgroundTexture.Apply();
            return backgroundTexture;
        }

        #endregion

        #region 打包处理

        /// <summary>
        /// 绘制打包按钮
        /// </summary>
        private void DrawBuildButton()
        {
            GUI.enabled = isAddVersion || configAsset.GetAllVersionCount() == 0;
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Build"))
            {
                isAutoRun = false;
                CheckAndBuild();
            }

            GUILayout.Space(10);

            if (GUILayout.Button("Build And Run"))
            {
                isAutoRun = true;
                CheckAndBuild();
            }
            GUILayout.EndHorizontal();
            GUILayout.Space(5);
        }

        /// <summary>
        /// 打包检查和打包
        /// </summary>
        private void CheckAndBuild()
        {
            if (!CheckBuildInfo())
            {
                ResizeWindow(extendSize);
            }
            else
            {
                if (BuildLogUpgrade.IsNeedUpgrade())
                    Debug.Log("Please upgrade before packaging.Upgrade through Edit ->Build Info ->Upgrade");
                else
                {
                    UpdatePlayerSettings();

                    UpdateBuildPlayerOptions();

                    BuildPlayerWindow.DefaultBuildMethods.BuildPlayer(GetBuildPlayerOptionsToMemory());
                }
            }
        }

        /// <summary>
        /// 检查打包信息
        /// </summary>
        private bool CheckBuildInfo()
        {
            appIDWarning = false;
            companyNameWarning = false;
            productNameWarning = false;
            versionWarning = false;
            //iconWarning = false;
            logWarning = false;

            if (string.IsNullOrWhiteSpace(appID))
            {
                appIDWarning = true;
                appIDWarningInfo = "Please enter the App ID";
                return false;
            }

            if (string.IsNullOrEmpty(companyName))
            {
                companyNameWarning = true;
                companyNameWarningInfo = "Please enter the company name";
                return false;
            }

            if (string.IsNullOrEmpty(productName))
            {
                productNameWarning = true;
                productNameWarningInfo = "Please enter the product name";
                return false;
            }

            if (string.IsNullOrEmpty(version))
            {
                versionWarning = true;
                versionWarningInfo = "Please enter the version";
                return false;
            }
            else if (IsExistVersion(version))
            {
                //这里如果是不同的Type,应该允许同版本的存在
                string buildType = configAsset.GetBuildType(version);
                if (type == buildType)
                {
                    versionWarning = true;
                    versionWarningInfo = "The version already exists";
                    return false;
                }
            }
            else if (!Version.TryParse(version, out _))
            {
                versionWarning = true;
                versionWarningInfo = "Invalid version format";
                return false;
            }

            //if (defaultIcon == null)
            //{
            //    iconWarning = true;
            //    iconWarningInfo = "Please select the icon";
            //    return false;
            //}

            if (string.IsNullOrEmpty(buildLog))
            {
                logWarning = true;
                logWarningInfo = "Please enter the packaging log";
                return false;
            }

            return true;
        }

        /// <summary>
        /// 判断版本是否存在
        /// </summary>
        /// <param name="version"></param>
        /// <returns></returns>
        public bool IsExistVersion(string version)
        {
            return configAsset.IsExistVersion(version);
        }

        /// <summary>
        /// 在打包前执行的回调
        /// 打包开始时，查看是否有打包日志文件，没有就创建
        /// </summary>
        /// <param name="report"></param>
        public void OnPreprocessBuild(BuildReport report) { }

        /// <summary>
        /// 在打包后执行的回调
        /// 1.将打包信息添加到版本管理中
        /// 2.更新最新打包信息
        /// 3.将打包日志写入到日志文件中
        /// 4.将打包日志文件拷贝到打包目录
        /// </summary>
        /// <param name="report"></param>
        public async void OnPostprocessBuild(BuildReport report)
        {
            SetBuildInfo();

            UpdateLastBuildInfo();

            await WriteEncrypBuildLogToHtml(lastBuildInfo, logConfigItem);

            WriteSoftPropertyToBuildDirectory(report, lastBuildInfo, logConfigItem);

            GenerateRegistryToolToBuildDirectory(report, lastBuildInfo);

            CopyBuildLogToProjectDirectory();

            if (isAutoRun)
            {
                AutoRunBuildExe(report);
            }

            isAddVersion = false;
        }

        /// <summary>
        /// 自动运行打包文件
        /// </summary>
        private void AutoRunBuildExe(BuildReport report)
        {
            string outputPath = report.summary.outputPath;

            if (File.Exists(outputPath))
            {
                try
                {
                    Process.Start(outputPath);
                }
                catch (Exception e)
                {
                    Debug.LogError($"Failed to open build log: {e.Message}");
                }
            }
        }

        #endregion

        #region BuildInfo打包信息操作

        /// <summary>
        /// 更新最新打包信息
        /// </summary>
        private void UpdateLastBuildInfo()
        {
            lastBuildInfo = GetLastBuildInfo(out int index);

            if (lastBuildInfo == null)
            {
                lastBuildInfo = GetPlayerBuildInfo();
            }

            UpdateBuildInfo(index, lastBuildInfo);
        }

        /// <summary>
        /// 获取最新打包信息
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public BuildInfo GetLastBuildInfo(out int index)
        {
            return configAsset.GetLastVersionBuildInfo(out index);
        }

        /// <summary>
        /// 更新打包信息
        /// </summary>
        /// <param name="index"></param>
        /// <param name="buildInfo"></param>
        private void UpdateBuildInfo(int index, BuildInfo buildInfo)
        {
            selectedVersionIndex = index;

            // 初始化为当前 PlayerSettings 中的值
            platform = buildInfo.platform;
            appID = buildInfo.appID;
            feature = buildInfo.feature;
            model = buildInfo.model;
            language = buildInfo.language;
            type = buildInfo.type;
            companyName = buildInfo.companyName;
            productName = buildInfo.productName;
            version = buildInfo.version;
            defaultIcon = buildInfo.defaultIcon;
            buildLog = buildInfo.log;
            buildTime = buildInfo.buildTime == default ? "" : "Build on " + buildInfo.buildTime;

            UpdateLogConfigIndex(buildInfo);

            UpdateBuildSettingsToMemory(index, buildInfo);
        }

        /// <summary>
        /// 更新日志相关索引
        /// </summary>
        /// <param name="buildInfo"></param>
        /// 这里如果没有对应的索引，那么就会返回-1，那么这个时候默认选择第一个索引
        private void UpdateLogConfigIndex(BuildInfo buildInfo)
        {
            selectedPlatformIndex = logConfigItem.GetPlatformsIndex(buildInfo.platform);
            if (selectedPlatformIndex == -1)
            {
                selectedPlatformIndex = 0;
                buildInfo.platform = logConfigItem.platforms[selectedPlatformIndex].key;
            }

            selectedFeatureIndex = logConfigItem.GetFeaturesIndex(buildInfo.feature);
            if (selectedFeatureIndex == -1)
            {
                selectedFeatureIndex = 0;
                buildInfo.feature = logConfigItem.features[selectedFeatureIndex].key;
            }

            selectedModelIndex = logConfigItem.GetModelsIndex(buildInfo.model);
            if (selectedModelIndex == -1)
            {
                selectedModelIndex = 0;
                buildInfo.model = logConfigItem.models[selectedModelIndex].key;
            }

            selectedLanguageIndex = logConfigItem.GetLanguagesIndex(buildInfo.language);
            if (selectedLanguageIndex == -1)
            {
                selectedLanguageIndex = 0;
                buildInfo.language = logConfigItem.languages[selectedLanguageIndex].key;
            }

            selectedTypeIndex = logConfigItem.GetTypesIndex(buildInfo.type);
            if (selectedTypeIndex == -1)
            {
                selectedTypeIndex = 0;
                buildInfo.type = logConfigItem.releaseTypes[selectedTypeIndex].key;
            }
        }

        /// <summary>
        /// 存储打包信息
        /// </summary>
        /// <returns></returns>
        public BuildInfo SetBuildInfo()
        {
            BuildInfo buildInfo = new BuildInfo();

            buildInfo.platform = platform;
            buildInfo.appID = appID;
            buildInfo.feature = feature;
            buildInfo.model = model;
            buildInfo.language = language;
            buildInfo.type = type;
            buildInfo.companyName = companyName;
            buildInfo.productName = productName;
            buildInfo.version = version;
            buildInfo.defaultIcon = defaultIcon;
            buildInfo.log = buildLog;
            buildInfo.buildTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            // 添加新的日志
            configAsset.AddBuildInfo(buildInfo);

            // 保存并刷新
            EditorUtility.SetDirty(configAsset);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();

            return buildInfo;
        }

        /// <summary>
        /// 删除打包信息
        /// </summary>
        /// <param name="version"></param>
        public async void RemoveBuildInfo(int index)
        {
            BuildInfo info = configAsset.GetBuildInfo(index);

            configAsset.RemoveBuildInfo(info.version, info.type);

            await LogInfoHtmlOutput.DeleteEncrypBuildLogByVersion(info.version, info.type);
        }

        #endregion

        #region PlayerSettings操作

        /// <summary>
        /// 获取 PlayerSettings 中的值
        /// </summary>
        /// <returns></returns>
        private BuildInfo GetPlayerBuildInfo()
        {
            BuildInfo buildInfo = new BuildInfo();

            buildInfo.companyName = PlayerSettings.companyName;
            buildInfo.appID = PlayerSettings.productName;
            buildInfo.productName = PlayerSettings.productName;
            buildInfo.version = PlayerSettings.bundleVersion;
            buildInfo.defaultIcon = FetchDefaultIcon();

            return buildInfo;
        }

        /// <summary>
        /// 获取默认图标
        /// </summary>
        /// <returns></returns>
        public static Texture2D FetchDefaultIcon()
        {
            // 获取 Default Icon
            Texture2D[] icons = PlayerSettings.GetIconsForTargetGroup(BuildTargetGroup.Unknown);

            return (icons.Length > 0 && icons[0] != null) ? icons[0] : null;
        }

        /// <summary>
        /// 保存 PlayerSettings 设置
        /// </summary>
        /// <param name="buildInfo"></param>
        private void UpdatePlayerSettings()
        {
            PlayerSettings.companyName = companyName;
            PlayerSettings.productName = appID;
            PlayerSettings.bundleVersion = version;
            PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Unknown, new[] { defaultIcon });
        }

        #endregion

        #region BuildPlayerOptions操作

        /// <summary>
        /// 更新打包项
        /// 在真正打包的前，BuildPlayerOptions.scenes和BuildPlayerOptions.locationPathName可能会改变
        /// </summary>
        private void UpdateBuildPlayerOptions()
        {
            BuildPlayerOptions playerOptions = GetBuildPlayerOptionsToMemory();

            // 获取所有设置为包含在构建中的场景
            EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes;
            string[] activeScenes = EditorBuildSettingsScene.GetActiveSceneList(scenes);

            playerOptions.scenes = activeScenes;

            string path = playerOptions.locationPathName;

            // 正则表达式模式，匹配".exe"之前的部分
            string pattern = @"(.*[/\\])?([^/\\]+)(?=\.exe$)";

            // 使用正则表达式进行替换
            path = Regex.Replace(path, pattern, m =>
                (m.Groups[1].Value ?? "") + PlayerSettings.productName); // 如果没有路径部分，则Groups[1]为空

            playerOptions.locationPathName = path;

            // 获取当前的 BuildTargetGroup
            playerOptions.targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;

            // 获取当前的 BuildTarget
            playerOptions.target = EditorUserBuildSettings.activeBuildTarget;

            UpdateBuildPlayerOptionsToMemory(playerOptions);
        }

        #endregion

        #region 内存操作

        /// <summary>
        /// 从内存中获取最新打包信息
        /// </summary>
        private void UpdateLastBuildSettingsFromMemory()
        {
            lastBuildInfo = GetBuildSettingsToMemory(out int versionIndex);

            UpdateBuildInfo(versionIndex, lastBuildInfo);
        }

        /// <summary>
        /// 检查内存中是否存在面板上的打包信息
        /// </summary>
        /// <returns></returns>
        private bool IsHaveBuildSettingsMemoryInfo()
        {
            return EditorPrefs.HasKey("SelectedVersionIndex")
                 && EditorPrefs.HasKey("Platform")
                 && EditorPrefs.HasKey("AppID")
                 && EditorPrefs.HasKey("Feature")
                 && EditorPrefs.HasKey("Model")
                 && EditorPrefs.HasKey("Language")
                 && EditorPrefs.HasKey("Type")
                 && EditorPrefs.HasKey("CompanyName")
                 && EditorPrefs.HasKey("ProductName")
                 && EditorPrefs.HasKey("Version")
                 && EditorPrefs.HasKey("DefaultIcon")
                 && EditorPrefs.HasKey("BuildLog");
        }

        /// <summary>
        /// 将面板上的打包信息写入到内存中
        /// 1、当打开面板时会将读取到的打包信息写入到内存中
        /// 2、当修改面板上的打包信息时会将修改后的打包信息写入到内存中
        /// 3、当版本选择时，更新面板信息后会将修改后的打包信息写入到内存中
        /// 4、当打包完成后会获取到最新的打包信息，写入到内存中
        /// </summary>
        /// <param name="index"></param>
        /// <param name="buildInfo"></param>
        private void UpdateBuildSettingsToMemory(int index, BuildInfo buildInfo)
        {
            EditorPrefs.SetInt("SelectedVersionIndex", index);
            EditorPrefs.SetString("BuildTime", buildInfo.buildTime);
            EditorPrefs.SetString("Platform", buildInfo.platform);
            EditorPrefs.SetString("AppID", buildInfo.appID);
            EditorPrefs.SetString("Feature", buildInfo.feature);
            EditorPrefs.SetString("Model", buildInfo.model);
            EditorPrefs.SetString("Language", buildInfo.language);
            EditorPrefs.SetString("Type", buildInfo.type);
            EditorPrefs.SetString("CompanyName", buildInfo.companyName);
            EditorPrefs.SetString("ProductName", buildInfo.productName);
            EditorPrefs.SetString("Version", buildInfo.version);
            EditorPrefs.SetString("DefaultIcon", buildInfo.defaultIcon == null ? "" : AssetDatabase.GetAssetPath(buildInfo.defaultIcon));
            EditorPrefs.SetString("BuildLog", buildInfo.log);
        }

        /// <summary>
        /// 从内存中获取打包信息
        /// </summary>
        /// <param name="versionIndex"></param>
        /// <returns></returns>
        private BuildInfo GetBuildSettingsToMemory(out int versionIndex)
        {
            BuildInfo buildInfo = new BuildInfo();

            versionIndex = EditorPrefs.GetInt("SelectedVersionIndex");
            buildInfo.buildTime = EditorPrefs.GetString("BuildTime");
            buildInfo.platform = EditorPrefs.GetString("Platform");
            buildInfo.appID = EditorPrefs.GetString("AppID");
            buildInfo.feature = EditorPrefs.GetString("Feature");
            buildInfo.model = EditorPrefs.GetString("Model");
            buildInfo.language = EditorPrefs.GetString("Language");
            buildInfo.type = EditorPrefs.GetString("Type");
            buildInfo.companyName = EditorPrefs.GetString("CompanyName");
            buildInfo.productName = EditorPrefs.GetString("ProductName");
            buildInfo.version = EditorPrefs.GetString("Version");
            string defaultIconPath = EditorPrefs.GetString("DefaultIcon");
            if (!string.IsNullOrEmpty(defaultIconPath))
                buildInfo.defaultIcon = AssetDatabase.LoadAssetAtPath(defaultIconPath, typeof(Texture2D)) as Texture2D;
            buildInfo.log = EditorPrefs.GetString("BuildLog");

            return buildInfo;
        }

        /// <summary>
        /// 从内存中删除打包信息
        /// </summary>
        private void RemoveBuildSettingsFromMemory()
        {
            EditorPrefs.DeleteKey("SelectedVersionIndex");
            EditorPrefs.DeleteKey("BuildTime");
            EditorPrefs.DeleteKey("Platform");
            EditorPrefs.DeleteKey("AppID");
            EditorPrefs.DeleteKey("Feature");
            EditorPrefs.DeleteKey("Model");
            EditorPrefs.DeleteKey("Language");
            EditorPrefs.DeleteKey("Type");
            EditorPrefs.DeleteKey("CompanyName");
            EditorPrefs.DeleteKey("ProductName");
            EditorPrefs.DeleteKey("Version");
            EditorPrefs.DeleteKey("DefaultIcon");
            EditorPrefs.DeleteKey("BuildLog");
        }

        /// <summary>
        /// 添加构建设置
        /// scenes、locationPathName可能会发生改变
        /// </summary>
        /// <param name="options"></param>
        private void UpdateBuildPlayerOptionsToMemory(BuildPlayerOptions options)
        {
            EditorPrefs.SetString("scenes", string.Join("|", options.scenes));
            EditorPrefs.SetString("locationPathName", options.locationPathName);
            EditorPrefs.SetString("assetBundleManifestPath", options.assetBundleManifestPath);
            EditorPrefs.SetInt("targetGroup", (int)options.targetGroup);
            EditorPrefs.SetInt("target", (int)options.target);
            EditorPrefs.SetInt("options", (int)options.options);
        }

        /// <summary>
        /// 获取保存的构建信息
        /// </summary>
        /// <returns></returns>
        private BuildPlayerOptions GetBuildPlayerOptionsToMemory()
        {
            BuildPlayerOptions options = new BuildPlayerOptions();
            options.scenes = EditorPrefs.GetString("scenes").Split('|');
            options.locationPathName = EditorPrefs.GetString("locationPathName");
            options.assetBundleManifestPath = EditorPrefs.GetString("assetBundleManifestPath");
            options.targetGroup = (BuildTargetGroup)EditorPrefs.GetInt("targetGroup");
            options.target = (BuildTarget)EditorPrefs.GetInt("target");
            options.options = (BuildOptions)EditorPrefs.GetInt("options");
            return options;
        }

        /// <summary>
        /// 移除BuildPlayerOptions
        /// </summary>
        private void RemoveBuildPlayerOptionsToMemory()
        {
            EditorPrefs.DeleteKey("scenes");
            EditorPrefs.DeleteKey("locationPathName");
            EditorPrefs.DeleteKey("assetBundleManifestPath");
            EditorPrefs.DeleteKey("targetGroup");
            EditorPrefs.DeleteKey("target");
            EditorPrefs.DeleteKey("options");
        }

        #endregion

        #region 日志处理

        /// <summary>
        /// 打开本地的build.log日志文件
        /// </summary>
        private void OpenBuildLog()
        {
            string localLogPath = PathManager.BuildLogHtmlPath;

            if (File.Exists(localLogPath))
            {
                try
                {
                    //设置验证token，那么在本地打开就不在需要登录验证
                    //LogInfoHtmlOutput.SetValidToken(localLogPath);
                    // 使用默认文本编辑器打开日志文件
                    Process.Start(localLogPath);
                }
                catch (Exception e)
                {
                    Debug.LogError($"Failed to open build log: {e.Message}");
                }
            }
            else
            {
                Debug.LogWarning($"Log file not found at: {localLogPath}");
            }
        }

        private async Task WriteEncrypBuildLogToHtml(BuildInfo lastBuildInfo, BuildConfigItem buildConfigItem)
        {
            await LogInfoHtmlOutput.WriteEncrypBuildLogToHtml(lastBuildInfo, buildConfigItem);
        }

        private void WriteSoftPropertyToBuildDirectory(BuildReport report, BuildInfo lastBuildInfo, BuildConfigItem buildConfigItem)
        {
            // 目标打包路径下的日志文件路径
            string targetInfoPath = PathManager.BuildOutputSoftwareInfoPath(report);

            SoftPropertyOutput.WriteSoftPropertyToBuildDirectory(targetInfoPath, lastBuildInfo, buildConfigItem);
        }

        private void GenerateRegistryToolToBuildDirectory(BuildReport report, BuildInfo lastBuildInfo)
        {
            string targetBatFilePath = PathManager.BuildOutputRegistryToolPath(report);

            RegistryToolGenerator.GenerateRegistryTool(targetBatFilePath, lastBuildInfo);
        }

        /// <summary>
        /// 在打包完成后将日志文件拷贝到工程目录
        /// </summary>
        /// <param name="report"></param>
        private void CopyBuildLogToProjectDirectory()
        {
            string htmlLogPath = PathManager.BuildLogHtmlPath;

            // 目标打包路径下的日志文件路径
            string targethtmlLogPath = "";

            if (!string.IsNullOrEmpty(buildProcessConfig.buildLogOutPath))
            {
                targethtmlLogPath = buildProcessConfig.buildLogOutPath;
                if (!targethtmlLogPath.Contains("CHANGELOG"))
                    targethtmlLogPath = Path.Combine(targethtmlLogPath, "CHANGELOG");
                targethtmlLogPath = Path.Combine(targethtmlLogPath, "changelog.html");
            }
            else
                targethtmlLogPath = PathManager.BuildOutputHtmlLogPath();

            try
            {
                // 检查本地日志文件是否存在
                if (File.Exists(htmlLogPath))
                {
                    string outDir = Path.GetDirectoryName(targethtmlLogPath);
                    if (!Directory.Exists(outDir))
                        Directory.CreateDirectory(outDir);

                    // 将本地日志文件拷贝到打包目录
                    File.Copy(htmlLogPath, targethtmlLogPath, overwrite: true);

                    Debug.Log($"Build html log copied to build directory: {targethtmlLogPath}");
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"Failed to copy build log to build directory: {e.Message}");
            }
        }

        #endregion
    }
}